package com.sscl.easyble.defaultImpl

import android.bluetooth.BluetoothGatt
import android.bluetooth.BluetoothGattCallback
import android.bluetooth.BluetoothGattCharacteristic
import android.bluetooth.BluetoothGattDescriptor
import android.bluetooth.BluetoothProfile
import android.os.Build
import androidx.annotation.RequiresApi
import com.sscl.easyble.InternalConstants
import com.sscl.easyble.Logger
import com.sscl.easyble.enums.BlePhy
import com.sscl.easyble.extensions.isMainThread
import com.sscl.easyble.extensions.stopConnectTimeoutTimer
import com.sscl.easyble.variable.GlobalConnectVariable

internal class DefaultMultiBluetoothGattCallback : BluetoothGattCallback() {

    private companion object {
        private const val TAG = "DefaultMultiBluetoothGattCallback"
    }

    override fun onPhyUpdate(gatt: BluetoothGatt, txPhy: Int, rxPhy: Int, status: Int) {
        val address = gatt.device?.address ?: return
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
            return
        }
        if (isMainThread()) {
            performDevicePhyUpdateListener(
                address,
                BlePhy.fromValue(txPhy),
                BlePhy.fromValue(rxPhy),
                status
            )
        } else {
            InternalConstants.handler.post {
                performDevicePhyUpdateListener(
                    address,
                    BlePhy.fromValue(txPhy),
                    BlePhy.fromValue(rxPhy),
                    status
                )
            }
        }
    }

    override fun onPhyRead(gatt: BluetoothGatt, txPhy: Int, rxPhy: Int, status: Int) {
        val address = gatt.device?.address ?: return
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
            return
        }
        if (isMainThread()) {
            performDevicePhyReadListener(
                address,
                BlePhy.fromValue(txPhy),
                BlePhy.fromValue(rxPhy),
                status
            )
        } else {
            InternalConstants.handler.post {
                performDevicePhyReadListener(
                    address,
                    BlePhy.fromValue(txPhy),
                    BlePhy.fromValue(rxPhy),
                    status
                )
            }
        }
    }

    override fun onConnectionStateChange(gatt: BluetoothGatt, status: Int, newState: Int) {
        val address = gatt.device?.address ?: return
        if (isMainThread()) {
            performDeviceConnectionStateChangedListener(address, status, newState)
        } else {
            InternalConstants.handler.post {
                performDeviceConnectionStateChangedListener(address, status, newState)
            }
        }
    }

    override fun onServicesDiscovered(gatt: BluetoothGatt, status: Int) {
        val address = gatt.device?.address ?: return
        if (isMainThread()) {
            performDeviceServicesDiscoveredListener(address, status)
        } else {
            InternalConstants.handler.post {
                performDeviceServicesDiscoveredListener(address, status)
            }
        }
    }

    override fun onCharacteristicRead(
        gatt: BluetoothGatt,
        characteristic: BluetoothGattCharacteristic,
        value: ByteArray,
        status: Int
    ) {
        characteristicRead(gatt, characteristic, value, status)
    }

    @Deprecated("Deprecated in Java")
    override fun onCharacteristicRead(
        gatt: BluetoothGatt,
        characteristic: BluetoothGattCharacteristic,
        status: Int
    ) {
        @Suppress("DEPRECATION")
        val value = characteristic.value
        characteristicRead(gatt, characteristic, value, status)
    }

    override fun onCharacteristicWrite(
        gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic, status: Int
    ) {
        Logger.log(TAG,"onCharacteristicWrite")
        val address = gatt.device?.address ?: return
        if (isMainThread()) {
            performDeviceCharacteristicWriteListener(address, characteristic, status)
        } else {
            InternalConstants.handler.post {
                performDeviceCharacteristicWriteListener(address, characteristic, status)
            }
        }
    }

    override fun onCharacteristicChanged(
        gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic, value: ByteArray
    ) {
        characteristicChanged(gatt, characteristic, value)
    }

    @Deprecated("Deprecated in Java")
    override fun onCharacteristicChanged(
        gatt: BluetoothGatt,
        characteristic: BluetoothGattCharacteristic
    ) {

        @Suppress("DEPRECATION")
        val value = characteristic.value
        characteristicChanged(gatt, characteristic, value)
    }

    override fun onDescriptorRead(
        gatt: BluetoothGatt, descriptor: BluetoothGattDescriptor, status: Int, value: ByteArray
    ) {
        descriptorRead(gatt, descriptor, value, status)
    }

    @Deprecated("Deprecated in Java")
    override fun onDescriptorRead(
        gatt: BluetoothGatt,
        descriptor: BluetoothGattDescriptor,
        status: Int
    ) {
        @Suppress("DEPRECATION")
        val value = descriptor.value
        descriptorRead(gatt, descriptor, value, status)
    }

    override fun onDescriptorWrite(
        gatt: BluetoothGatt, descriptor: BluetoothGattDescriptor, status: Int
    ) {
        Logger.log(TAG,"onDescriptorWrite")
        val address = gatt.device?.address ?: return
        if (isMainThread()) {
            performDeviceDescriptorWriteListener(address, descriptor, status)
        } else {
            InternalConstants.handler.post {
                performDeviceDescriptorWriteListener(address, descriptor, status)
            }
        }
    }

    override fun onReliableWriteCompleted(gatt: BluetoothGatt, status: Int) {
        val address = gatt.device?.address ?: return
        if (isMainThread()) {
            performReliableWriteCompletedListener(address, status)
        } else {
            InternalConstants.handler.post {
                performReliableWriteCompletedListener(address, status)
            }
        }
    }

    override fun onReadRemoteRssi(gatt: BluetoothGatt, rssi: Int, status: Int) {
        val address = gatt.device?.address ?: return
        if (isMainThread()) {
            performDeviceRssiReadListener(address, rssi, status)
        } else {
            InternalConstants.handler.post {
                performDeviceRssiReadListener(address, rssi, status)
            }
        }
    }

    override fun onMtuChanged(gatt: BluetoothGatt, mtu: Int, status: Int) {
        val address = gatt.device?.address ?: return
        if (isMainThread()) {
            performDeviceMtuChangedListener(address, mtu, status)
        } else {
            InternalConstants.handler.post {
                performDeviceMtuChangedListener(address, mtu, status)
            }
        }
    }

    override fun onServiceChanged(gatt: BluetoothGatt) {
        super.onServiceChanged(gatt)
        Logger.log(TAG, "address ${gatt.device.address} onServiceChanged")
    }

    /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
     *
     * 私有方法
     *
     * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

    private fun characteristicRead(
        gatt: BluetoothGatt,
        characteristic: BluetoothGattCharacteristic,
        value: ByteArray,
        status: Int
    ) {
        val address = gatt.device?.address ?: return
        if (isMainThread()) {
            performDeviceCharacteristicReadListener(address, characteristic, value, status)
        } else {
            InternalConstants.handler.post {
                performDeviceCharacteristicReadListener(address, characteristic, value, status)
            }
        }
    }

    private fun characteristicChanged(
        gatt: BluetoothGatt,
        characteristic: BluetoothGattCharacteristic,
        value: ByteArray
    ) {
        val address = gatt.device?.address ?: return
        if (isMainThread()) {
            performDeviceCharacteristicNotifyListener(address, characteristic, value)
        } else {
            InternalConstants.handler.post {
                performDeviceCharacteristicNotifyListener(address, characteristic, value)
            }
        }
    }

    private fun descriptorRead(
        gatt: BluetoothGatt,
        descriptor: BluetoothGattDescriptor,
        value: ByteArray,
        status: Int
    ) {
        val address = gatt.device?.address ?: return
        if (isMainThread()) {
            performDeviceDescriptorReadListener(address, descriptor, value, status)
        } else {
            InternalConstants.handler.post {
                performDeviceDescriptorReadListener(address, descriptor, value, status)
            }
        }
    }

    private fun performDeviceConnectionStateChangedListener(
        address: String,
        gattState: Int,
        newState: Int
    ) {
        when (newState) {
            BluetoothProfile.STATE_DISCONNECTED -> {
                Logger.log(TAG, "address $address 断开连接")
                Logger.log(TAG, "address $address disconnect")
                GlobalConnectVariable.connectedStateList[address] = false
                GlobalConnectVariable.bluetoothGattConnectStateChangedListenerList[address]?.onDisconnected(
                    address, gattState
                )
            }

            BluetoothProfile.STATE_CONNECTING -> {
                Logger.log(TAG, "address $address 正在连接")
                Logger.log(TAG, "address $address connecting")
                GlobalConnectVariable.bluetoothGattConnectStateChangedListenerList[address]?.onConnecting(
                    address, gattState
                )
            }


            BluetoothProfile.STATE_CONNECTED -> {
                Logger.log(TAG, "address $address 连接成功")
                Logger.log(TAG, "address $address connected")
                GlobalConnectVariable.bluetoothGattConnectStateChangedListenerList[address]?.onConnected(
                    address, gattState
                )
                val succeed = GlobalConnectVariable.gattList[address]?.discoverServices()
                if (succeed == false) {
                    Logger.log(TAG, "address $address 发现服务请求失败")
                    Logger.log(TAG, "address $address discoverServices failed")
                    GlobalConnectVariable.bluetoothGattConnectStateChangedListenerList[address]?.onDiscoverServicesFailed(
                        address
                    )
                }
            }

            BluetoothProfile.STATE_DISCONNECTING -> {
                Logger.log(TAG, "address $address 正在断开连接")
                Logger.log(TAG, "address $address disconnecting")
                GlobalConnectVariable.bluetoothGattConnectStateChangedListenerList[address]?.onDisconnecting(
                    address, gattState
                )
            }

            else -> {
                Logger.log(TAG, "address $address 未知状态")
                Logger.log(TAG, "address $address unknown status")
                GlobalConnectVariable.bluetoothGattConnectStateChangedListenerList[address]?.onUnknownStatus(
                    address, gattState, newState
                )
            }
        }
    }

    /**
     * 服务发现完成
     */
    private fun performDeviceServicesDiscoveredListener(address: String, gattState: Int) {
        if (gattState == BluetoothGatt.GATT_SUCCESS) {
            GlobalConnectVariable.connectedStateList[address] = true
        }
        address.stopConnectTimeoutTimer()
        GlobalConnectVariable.bluetoothGattConnectStateChangedListenerList[address]?.onServicesDiscovered(
            address,
            gattState
        )
    }

    /**
     * 描述符读取完成
     */
    private fun performDeviceDescriptorReadListener(
        address: String,
        descriptor: BluetoothGattDescriptor,
        value: ByteArray,
        gattState: Int
    ) {
        GlobalConnectVariable.onDescriptorDataOptionListenerList[address]?.onDescriptorRead(
            address,
            descriptor,
            value,
            gattState
        )
    }

    /**
     * 描述写入操作结果
     */
    private fun performDeviceDescriptorWriteListener(
        address: String,
        descriptor: BluetoothGattDescriptor,
        gattState: Int
    ) {
        GlobalConnectVariable.onDescriptorDataOptionListenerList[address]?.onDescriptorWrite(
            address,
            descriptor,
            gattState
        )
    }

    /**
     * 描述写入操作结果
     */
    private fun performReliableWriteCompletedListener(
        address: String,
        gattState: Int
    ) {
        GlobalConnectVariable.onReliableWriteCompletedListenerList[address]?.onReliableWriteCompleted(
            address,
            gattState
        )
    }

    /**
     * 特征读取完成
     */
    private fun performDeviceCharacteristicReadListener(
        address: String,
        characteristic: BluetoothGattCharacteristic,
        value: ByteArray,
        gattState: Int
    ) {
        GlobalConnectVariable.onCharacteristicDataOptionsListenerList[address]?.onCharacteristicRead(
            address,
            characteristic,
            value,
            gattState
        )
    }

    /**
     * 特征写入操作结果
     */
    private fun performDeviceCharacteristicWriteListener(
        address: String,
        characteristic: BluetoothGattCharacteristic,
        gattState: Int
    ) {
        GlobalConnectVariable.onCharacteristicDataOptionsListenerList[address]?.onCharacteristicWrite(
            address,
            characteristic,
            gattState
        )
    }

    /**
     * 特征通知
     */
    private fun performDeviceCharacteristicNotifyListener(
        address: String,
        characteristic: BluetoothGattCharacteristic,
        value: ByteArray
    ) {
        GlobalConnectVariable.onCharacteristicDataOptionsListenerList[address]?.onCharacteristicNotify(
            address,
            characteristic,
            value
        )
    }

    /**
     * 设备RSSI读取操作结果
     */
    private fun performDeviceRssiReadListener(address: String, rssi: Int, gattState: Int) {
        GlobalConnectVariable.onReadRemoteRssiListenerList[address]?.onReadRemoteRssi(
            address,
            rssi,
            gattState
        )
    }

    /**
     * 设备Mtu变化通知
     */
    private fun performDeviceMtuChangedListener(address: String, mtu: Int, status: Int) {
        GlobalConnectVariable.onMtuChangedListenerList[address]?.onMtuChanged(address, mtu, status)
    }

    /**
     * 设备phy更新通知
     * @param address 设备地址
     *  @param txPhy 发送phy
     *  @param rxPhy 接收phy
     *  @param gattState 连接状态
     */
    @RequiresApi(Build.VERSION_CODES.O)
    private fun performDevicePhyUpdateListener(
        address: String,
        txPhy: BlePhy,
        rxPhy: BlePhy,
        gattState: Int
    ) {
        GlobalConnectVariable.onPhyOptionsListenerList[address]?.onPhyUpdate(
            address,
            txPhy,
            rxPhy,
            gattState
        )
    }

    @RequiresApi(Build.VERSION_CODES.O)
    private fun performDevicePhyReadListener(
        address: String,
        txPhy: BlePhy,
        rxPhy: BlePhy,
        gattState: Int
    ) {
        GlobalConnectVariable.onPhyOptionsListenerList[address]?.onPhyRead(
            address,
            txPhy,
            rxPhy,
            gattState
        )
    }
}